package org.paboo.chart.code128;

import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.paboo.Util.ParameterObject;
import org.paboo.Util.ZxingImage;
import org.paboo.http.BaseServlet;
import org.paboo.http.HttpMethod;

import com.google.gson.Gson;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.oned.Code128Writer;

public class Code128Servlet extends BaseServlet {

	private static final long serialVersionUID = -8770983696806841283L;
	private Logger log = LogManager.getLogger(getClass());

	@Override
	protected void processRequest(HttpServletRequest request, HttpServletResponse response, HttpMethod method)
			throws ServletException, IOException {
		Code128Entity p = new Code128Entity();
		if(method == HttpMethod.GET) {
			String ctx = getParameterWithDefault(request, "data", ParameterObject.DEFAULT_CONTECT);
			String encoding = StandardCharsets.UTF_8.name();
			ctx = URLDecoder.decode(ctx, encoding);
			ctx = new String(ctx.getBytes(encoding), StandardCharsets.ISO_8859_1);
			p.setData(ctx);
			
			p.setFormat(getParameterWithDefault(request, "format", "png"));
			String[] size = getParameterWithDefault(request, "size", "128x64").split("x");
			p.setWidth(Integer.valueOf(size[0]));
			p.setHeight(Integer.valueOf(size[1]));
		} else if(method == HttpMethod.POST) {
			BufferedReader br = new BufferedReader(
					new InputStreamReader(request.getInputStream(), request.getCharacterEncoding()));
			Gson gson = new Gson();
			p = gson.fromJson(br, Code128Entity.class);
			if(!ParameterObject.hasText(p.getData())){
				p.setData(ParameterObject.DEFAULT_CONTECT);
			}
			if(!ParameterObject.hasText(p.getFormat())){
				p.setFormat("png");
			}
			if(!ParameterObject.hasInteger(p.getWidth()) || !ParameterObject.hasInteger(p.getWidth())) {
				p.setHeight(64);
				p.setWidth(128);
			}
			log.info(gson.toJson(p));
		} else {
			response.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, "Request error!!!");
			return;
		}

		BufferedImage data = null;
		try {
			BitMatrix matrix = new Code128Writer().encode(p.getData(), BarcodeFormat.CODE_128, p.getWidth(), p.getHeight());
			log.debug("Matrix size:" + matrix.getWidth() + "x" + matrix.getHeight());
			data = ZxingImage.toBufferedImage(matrix, ZxingImage.WHITE, ZxingImage.BLACK);
		} catch (WriterException e) {
			String errorMsg = "Create Fail!!!";
			if (log.isDebugEnabled()) {
				log.error(errorMsg, e);
			} else {
				log.error(errorMsg);
			}
			response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, errorMsg);
			return;
		}
		
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		if (!ImageIO.write(data, p.getFormat(), out)) {
			log.error("Could not write an image of format " + p.getFormat());
			throw new IOException("Could not write an image of format " + p.getFormat());
		}
		response.setContentType("image/" + p.getFormat());
		response.setContentLength(out.size());
		response.getOutputStream().write(out.toByteArray());
	}

}
